﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.WorkItemTracking.Client;
using System.IO;
using System.Configuration;

namespace MoveSharedQueries
{
    class Program
    {
     
        static void Main(string[] args)
        {
          
             CopySharedQuery();
             Console.WriteLine("Query Copy opertion completed!!!");
              Console.ReadKey();
        
        }

        private  static  void CopySharedQuery()
        {
            List<SharedQueryInfo> lstqueryinfo=new List<SharedQueryInfo>();
            try
            {
                lstqueryinfo = getConfig();
                ProcessQueryFolder(lstqueryinfo);
            }
            catch (Exception ex)
            {

                Console.WriteLine(ex.Message);
                Logging.Log(ex.Message + "\n Stack Trace :" + ex.StackTrace);
            }
        }

        private static void ProcessQueryFolder(List<SharedQueryInfo> lstshareqryinfo)
        {
            try
            {

           
             Console.WriteLine( "Preparing source TFS connection" );
             QueryHierarchy sourceqryhirchy = getQueryHierarchy(getWorkItemStore(lstshareqryinfo[0].Serverurl), lstshareqryinfo[0].ProjectName);
            Console.WriteLine("Preparing target TFS connection");
            QueryHierarchy destqryhirchy = getQueryHierarchy(getWorkItemStore(lstshareqryinfo[1].Serverurl), lstshareqryinfo[1].ProjectName);
            Console.WriteLine("Processing query folders and queries\n");
            QueryFolder sourcefolder=null;
               QueryFolder targetFolder=null;
            if(lstshareqryinfo[0].Subfolder =="")
            {
                sourcefolder=getQueryFolder(sourceqryhirchy ,lstshareqryinfo[0].Toplevelfolder );
            }
            else
            {
                sourcefolder=initialFolder(getQueryFolder(sourceqryhirchy,lstshareqryinfo[0].Toplevelfolder ),lstshareqryinfo[0].Subfolder );
            }
            
        if(lstshareqryinfo[1].Subfolder =="")
            {
                targetFolder=getQueryFolder(destqryhirchy ,lstshareqryinfo[1].Toplevelfolder );
            }
            else
            {
                targetFolder=initialFolder(getQueryFolder(destqryhirchy,lstshareqryinfo[1].Toplevelfolder ),lstshareqryinfo[0].Subfolder );
            }
                
                
                
            copyQueries(sourcefolder,targetFolder,"",destqryhirchy,0,0,0);
            
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                Logging.Log(ex.Message + "\n Stack Trace :" + ex.StackTrace);

            }
           }

        private static QueryDefinition  GetQueryDefination(QueryFolder inputfolder)
        {
            QueryDefinition  objquerydef=null;
            try
            {
                foreach (QueryItem item in inputfolder)
                {
                    if (item.GetType() == typeof(QueryFolder))
                    {
                        GetQueryDefination((QueryFolder)item);
                    }
                    else  if (item.GetType() == typeof(QueryDefinition ))
                    {
                        objquerydef = (QueryDefinition)item;
                    }
                }

            }
            catch (Exception ex )
            {
                
                  Console.WriteLine(ex.Message);
                Logging.Log(ex.Message + "\n Stack Trace :" + ex.StackTrace);
            }
            return objquerydef;
        }

        //private static void copyQueries(QueryFolder sourcefolder, QueryFolder destinationfolder,string indent,QueryHierarchy destqryhierarchy)
        //{
        //    Console.WriteLine("Total queries found : " + sourcefolder.Count.ToString());
        //    Logging.Log("Total queries found : " + sourcefolder.Count.ToString());
        //    int Scounter=0,FCounter=0,AEcounter = 0;
        //     foreach (QueryDefinition  item in sourcefolder )
        //    {
        //        try
        //        {
        //            string qrytext = item.QueryText;
        //            //Get Destination Area Path
        //            if (qrytext.Contains("[System.AreaPath]"))
        //            {
        //                qrytext = ParseMappingXML.GetDestinationAreaPath(qrytext);
        //            }
                  
        //            //Get Destination Iteration Path
        //            if (qrytext.Contains("[System.IterationPath]"))
        //            {
        //                qrytext = ParseMappingXML.GetDestinationIterationPath(qrytext);
        //            }

        //            //Get Markets clause
        //            if (qrytext.Contains("[Microsoft.VSTS.Common.Markets]"))
        //            {
        //                qrytext = ParseMappingXML.GetDestinationMarketsclause(qrytext);
        //            }

        //            QueryDefinition objdf = new QueryDefinition(item.Name, qrytext);
                    
                  
        //            Console.WriteLine("Saving Query: " + item.Name);
        //            Logging.Log("Saving Query: " + item.Name);
        //            if (destinationfolder.Contains(item.Name))
        //            {
        //                AEcounter++;
        //                Console.WriteLine("Query : " + item.Name + " already exists in  " + destinationfolder.Path);
        //                Logging.Log("Query : " + item.Name + " already exists in  " + destinationfolder.Path);
        //            }
        //            else
        //            {
        //                destinationfolder.Add(objdf);
        //                destqryhierarchy.Save();
        //                Scounter++;
        //                Console.WriteLine("Saved Query: " + item.Name + " in " + destinationfolder.Path);
        //                Logging.Log("Saved Query: " + item.Name + " in " + destinationfolder.Path);
        //            }
                    
        //        }
        //        catch (Exception ex)
        //        {
        //            FCounter++;
        //            destqryhierarchy.Refresh();
        //            Console.WriteLine(ex.Message);
        //            Logging.Log(ex.Message);
                     
        //        }   
               
                      
        //    }
            
        //     string summary = "New queries saved::" + Scounter + "||Already Existing queries::" + AEcounter + "||Saving failed for queries::" + FCounter;
        //     Console.WriteLine("Query Copy opertion completed for  queries.\n"+summary );
        //     Logging.Log(summary );
        //}

        private static void copyQueries(QueryFolder sourcefolder, QueryFolder destinationfolder, string indent, QueryHierarchy destqryhierarchy, int Scounter, int FCounter, int AEcounter)
        {
                     
            QueryDefinition objquerydef = null;
            QueryFolder objfolder = null;
            foreach (QueryItem  item in sourcefolder)
            {

                if (item.GetType() == typeof(QueryFolder))
                {
                    if (!destinationfolder.Contains(item.Name))
                    {
                        objfolder = new QueryFolder(item.Name);
                        destinationfolder.Add(objfolder);
                        destqryhierarchy.Save();
                        destqryhierarchy.Refresh();
                    }
                    else if (destinationfolder.Contains(item.Name))
                    {
                        objfolder =(QueryFolder) destinationfolder[item.Name];
                    }

                    copyQueries((QueryFolder)item, objfolder, "", destqryhierarchy,Scounter,FCounter,AEcounter);
                }
                else if (item.GetType() == typeof(QueryDefinition))
                {
                    objquerydef = (QueryDefinition)item;
                     try
                        {
                            string qrytext = objquerydef.QueryText;
                            //Get Destination Area Path
                            if (qrytext.Contains("[System.AreaPath]"))
                            {
                                qrytext = ParseMappingXML.GetDestinationAreaPath(qrytext);
                            }

                            //Get Destination Iteration Path
                            if (qrytext.Contains("[System.IterationPath]"))
                            {
                                qrytext = ParseMappingXML.GetDestinationIterationPath(qrytext);
                            }

                            //Get Markets clause
                            if (qrytext.Contains("[Microsoft.VSTS.Common.Markets]"))
                            {
                                qrytext = ParseMappingXML.GetDestinationMarketsclause(qrytext);
                            }

                            QueryDefinition objdf = new QueryDefinition(objquerydef.Name, qrytext);


                            Console.WriteLine("Saving Query: " + objquerydef.Name);
                            Logging.Log("Saving Query: " + objquerydef.Name);
                            if (destinationfolder.Contains(objquerydef.Name))
                            {
                                AEcounter++;
                                Console.WriteLine("Query : " + objquerydef.Name + " already exists in  " + destinationfolder.Path);
                                Logging.Log("Query : " + objquerydef.Name + " already exists in  " + destinationfolder.Path);
                            }
                            else
                            {
                                destinationfolder.Add(objdf);
                                destqryhierarchy.Save();
                                Scounter++;
                                Console.WriteLine("Saved Query: " + objquerydef.Name + " in " + destinationfolder.Path);
                                Logging.Log("Saved Query: " + objquerydef.Name + " in " + destinationfolder.Path);
                            }

                        }
                        catch (Exception ex)
                        {
                            FCounter++;
                            destqryhierarchy.Refresh();
                            Console.WriteLine(ex.Message);
                            Logging.Log(ex.Message);

                        }
                }


            }

            string summary = "New queries saved::" + Scounter + "||Already Existing queries::" + AEcounter + "||Saving failed for queries::" + FCounter;
            Logging.Log(summary);
        }

        private static QueryFolder  initialFolder (QueryFolder parentFolder , string subFolder )
        {
            QueryFolder tmp=null;

            if (parentFolder.Contains( subFolder))
            {
                tmp = (QueryFolder)parentFolder[subFolder];
            }
          else 
            {
               tmp= new QueryFolder( subFolder, parentFolder );
            }
            return tmp;
        }
        private static QueryFolder getQueryFolder(QueryHierarchy qryhirch,string toplevel)
        {
            QueryFolder objqryfolder=null;
            foreach (QueryFolder flder in qryhirch)
            {
                if (flder.Name==toplevel )
                {
                    objqryfolder = flder;
                }
            }
            return objqryfolder;

        }
        private static QueryHierarchy    getQueryHierarchy(WorkItemStore objworkitemstore,string projectname)
        {
              ProjectCollection  teamProjects  = objworkitemstore.Projects;
              Project thisProject = teamProjects[ projectname ];
              return thisProject.QueryHierarchy ;

        }
        private static WorkItemStore   getWorkItemStore(string serverURI)
        {
            Console.WriteLine("Connecting to {0}...", serverURI );
            TfsTeamProjectCollection  tfs = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(new Uri(serverURI));
            WorkItemStore SrcworkitemStore = (WorkItemStore)tfs.GetService(typeof(WorkItemStore));
            return SrcworkitemStore;
        }
        private static Items   getItems (string line) 
        {
            char[] splitter={'*'};
            string[] items = line.Split(splitter);
            Items thisitem = new Items();
           thisitem.SourceItem=  items[0].ToString().Trim();
           thisitem.DestItem =  items[1].ToString().Trim();
           return thisitem;
        }
    


private static List<SharedQueryInfo> getConfig()
{
    SharedQueryInfo SourceQueryInfo = new SharedQueryInfo();
    SharedQueryInfo DestinationQueryInfo = new SharedQueryInfo();
    List<SharedQueryInfo> lstsharedqryinfo = new List<SharedQueryInfo>();
    
    //Get Source Query Configurations
    SourceQueryInfo.Serverurl = ConfigurationManager.AppSettings["SourceTFSserverUrl"].ToString();
    SourceQueryInfo.ProjectName = ConfigurationManager.AppSettings["SourceProject"].ToString();
    SourceQueryInfo.Toplevelfolder = ConfigurationManager.AppSettings["SourceTopFolder"].ToString();
    SourceQueryInfo.Subfolder = ConfigurationManager.AppSettings["SourceSubFolder"].ToString();

    //Get Destination Query Configuration
    DestinationQueryInfo.Serverurl = ConfigurationManager.AppSettings["DestTFSserverUrl"].ToString();
    DestinationQueryInfo.ProjectName = ConfigurationManager.AppSettings["DestProject"].ToString();
    DestinationQueryInfo.Toplevelfolder = ConfigurationManager.AppSettings["DestTopFolder"].ToString();
    DestinationQueryInfo.Subfolder = ConfigurationManager.AppSettings["DestSubFolder"].ToString();
    
    
    lstsharedqryinfo.Add(SourceQueryInfo);
    lstsharedqryinfo.Add(DestinationQueryInfo);
    return lstsharedqryinfo;
}
   
    

    }
    class SharedQueryInfo
    {
        public string  Serverurl { get; set; }
        public string  ProjectName { get; set; }
        public string  Toplevelfolder { get; set; }
        public string Subfolder { get; set; }
    }
    class Items
    {
        public string SourceItem { get; set; }
        public string DestItem { get; set; }
    }
}
